import traceback
from playwright.sync_api import sync_playwright
import time
import os
import sys
import shutil
import re
import winreg
from typing import List, Optional
import random

def get_chrome_installation_paths() -> List[str]:
    """获取Windows系统上所有Chrome浏览器的安装路径"""
    possible_paths = []
    
    # 1. 从注册表中获取Chrome安装路径（优化版）
    try:
        # 尝试访问多个可能的注册表位置
        registry_paths = [
            r"Software\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe",
            r"Software\Google\Chrome\BLBeacon",  # Chrome安装信息注册表
            r"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe"  # 64位系统32位应用注册表
        ]
        
        for reg_path in registry_paths:
            try:
                key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, reg_path)
                path, _ = winreg.QueryValueEx(key, "")
                if os.path.exists(path):
                    possible_paths.append(path)
                winreg.CloseKey(key)
                break  # 找到有效路径后退出循环
            except (FileNotFoundError, PermissionError):
                traceback.print_exc()
                continue  # 继续尝试下一个注册表路径
    except Exception as e:
        print(f"注册表访问错误: {str(e)}")
    
    # 2. 检查常见安装位置（包含不同版本）
    common_locations = [
        r"C:\Program Files\Google\Chrome\Application",
        r"C:\Program Files (x86)\Google\Chrome\Application",
        os.path.expandvars(r"%LOCALAPPDATA%\Google\Chrome\Application"),
        os.path.expandvars(r"%PROGRAMFILES%\Google\Chrome Beta\Application"),
        os.path.expandvars(r"%PROGRAMFILES(x86)%\Google\Chrome Beta\Application"),
        os.path.expandvars(r"%LOCALAPPDATA%\Google\Chrome Beta\Application"),
        os.path.expandvars(r"%PROGRAMFILES%\Google\Chrome Dev\Application"),
        os.path.expandvars(r"%PROGRAMFILES(x86)%\Google\Chrome Dev\Application"),
        os.path.expandvars(r"%LOCALAPPDATA%\Google\Chrome Dev\Application"),
        os.path.expandvars(r"%PROGRAMFILES%\Google\Chrome SxS\Application"),  # Canary版本
        os.path.expandvars(r"%PROGRAMFILES(x86)%\Google\Chrome SxS\Application"),
    ]
    
    for location in common_locations:
        chrome_exe = os.path.join(location, "chrome.exe")
        if os.path.exists(chrome_exe):
            possible_paths.append(chrome_exe)
    
    # 3. 检查企业部署和便携版
    program_data = os.environ.get("ProgramData", r"C:\ProgramData")
    enterprise_path = os.path.join(program_data, r"Google\Chrome\Application\chrome.exe")
    if os.path.exists(enterprise_path):
        possible_paths.append(enterprise_path)
    
    app_data = os.environ.get("APPDATA", "")
    if app_data:
        portable_path = os.path.join(app_data, r"Google\Chrome\Application\chrome.exe")
        if os.path.exists(portable_path):
            possible_paths.append(portable_path)
    
    # 4. 额外检查：通过环境变量和文件搜索
    if not possible_paths:
        for drive in ['C:', 'D:', 'E:', 'F:']:  # 检查常见盘符
            search_path = os.path.join(drive, "Program Files", "Google", "Chrome", "Application", "chrome.exe")
            if os.path.exists(search_path):
                possible_paths.append(search_path)
            search_path = os.path.join(drive, "Program Files (x86)", "Google", "Chrome", "Application", "chrome.exe")
            if os.path.exists(search_path):
                possible_paths.append(search_path)
    
    # 去重并验证有效性
    unique_paths = list(set(possible_paths))
    return [path for path in unique_paths if os.path.exists(path) and os.access(path, os.X_OK)]

def get_latest_chrome_version_path(paths: List[str]) -> Optional[str]:
    """从路径列表中选择版本号最新的Chrome路径"""
    if not paths:
        return None
    
    version_pattern = re.compile(r"\\(\d+\.\d+\.\d+\.\d+)\\")
    versions = []
    
    for path in paths:
        match = version_pattern.search(path)
        if match:
            version_str = match.group(1)
            version_tuple = tuple(map(int, version_str.split('.')))
            versions.append((version_tuple, path))
        else:
            versions.append(((-1,), path))  # 无法提取版本号的排在最后
    
    versions.sort(key=lambda x: x[0], reverse=True)
    return versions[0][1]

def get_real_chrome_path() -> Optional[str]:
    """自动检测系统中最新版本的Chrome路径，支持Windows/macOS/Linux"""
    if sys.platform == "win32":
        all_paths = get_chrome_installation_paths()
        if all_paths:
            return get_latest_chrome_version_path(all_paths)
    
    elif sys.platform == "darwin":
        return "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
    
    elif sys.platform.startswith("linux"):
        from shutil import which
        for bin_name in ["google-chrome", "chrome", "chromium"]:
            path = which(bin_name)
            if path:
                return path
    
    return None

# 自定义用户数据目录，避免每次重新登录
USER_DATA_DIR = os.path.join(os.getcwd(), "baidu_user_data")

def login_and_search_baidu():
    """使用最新版Chrome登录百度并执行搜索"""
    chrome_path = get_real_chrome_path()
    if not chrome_path:
        print("错误：未找到Chrome浏览器，请先安装")
        return
    
    print(f"使用Chrome路径：{chrome_path}")
    
    try:
        with sync_playwright() as p:
            # 启动真实Chrome浏览器，添加反检测参数
            context = p.chromium.launch_persistent_context(
                user_data_dir=USER_DATA_DIR,
                executable_path=chrome_path,
                headless=False,
                args=[
                    '--disable-infobars',
                    '--disable-blink-features=AutomationControlled',
                    '--disable-features=IsolateOrigins,site-per-process',
                    '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                    '--no-sandbox',
                    '--disable-dev-shm-usage',
                    '--disable-web-security',
                    '--disable-features=VizDisplayCompositor',
                ],
                ignore_default_args=["--enable-automation"]
            )
            
            # 增强反检测：修改浏览器指纹
            context.add_init_script("""
                // 隐藏自动化标识
                Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
                // 修改插件信息
                Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
                // 修改语言
                Object.defineProperty(navigator, 'languages', { get: () => ['zh-CN', 'zh'] });
                // 模拟真实Chrome对象
                window.chrome = { runtime: { id: '' }, };
                // 模拟WebGL指纹
                const originalGetParameter = WebGLRenderingContext.prototype.getParameter;
                WebGLRenderingContext.prototype.getParameter = function(parameter) {
                    if (parameter === 37445) return 'NVIDIA Corporation'; // UNMASKED_VENDOR_WEBGL
                    if (parameter === 37446) return 'NVIDIA GeForce GTX 1080 OpenGL Engine'; // UNMASKED_RENDERER_WEBGL
                    return originalGetParameter.call(this, parameter);
                };
            """)
            
            page = context.new_page()
            page.set_default_timeout(30000)  # 增加超时时间到30秒
            
            try:
                # 打开百度并处理登录
                print("正在打开百度...")
                page.goto("https://www.baidu.com", wait_until="domcontentloaded")
                print("百度页面加载完成")
                
                # 等待页面完全加载
                page.wait_for_load_state("networkidle", timeout=10000)
                
                # 使用更精确的选择器来检查登录按钮
                login_selectors = [
                    "a[name='tj_login']",  # 主要的登录链接
                    "#s-top-loginbtn",     # 顶部登录按钮
                    "a.lb[name='tj_login']"  # 带class的登录链接
                ]
                
                login_found = False
                for selector in login_selectors:
                    try:
                        if page.locator(selector).is_visible():
                            print("找到登录按钮，请在30秒内扫码登录百度...")
                            page.click(selector)
                            login_found = True
                            break
                    except Exception:
                        continue
                
                if not login_found:
                    print("未找到登录按钮，可能已经登录或页面结构发生变化")
                
                # 等待登录完成
                if login_found:
                    page.wait_for_timeout(30000)  # 等待扫码登录
                
                # 执行搜索操作（添加随机延迟模拟人类行为）
                print("正在执行搜索...")
                search_input = page.locator("input#kw")
                if search_input.is_visible():
                    search_input.fill("iran missile")
                    time.sleep(random.uniform(0.5, 1.2))  # 随机输入延迟
                    page.keyboard.press("Enter")
                    
                    # 等待搜索结果加载
                    try:
                        page.wait_for_selector("div#content_left", timeout=15000)
                        print("搜索完成，页面保持30秒以便查看")
                        time.sleep(30)
                    except Exception as e:
                        print(f"等待搜索结果时出错: {e}")
                        print("页面将保持打开状态以便调试...")
                        time.sleep(60)
                else:
                    print("未找到搜索输入框")
                    time.sleep(30)
                
            except Exception as e:
                print(f"执行过程中发生错误: {e}")
                print("页面将保持打开状态以便调试...")
                time.sleep(60)  # 保持页面打开60秒用于调试
            
            finally:
                try:
                    context.close()
                except Exception as e:
                    print(f"关闭浏览器时出错: {e}")
                    
    except Exception as e:
        print(f"启动浏览器时发生错误: {e}")
        print("请检查Chrome浏览器是否正确安装")

if __name__ == "__main__":
    login_and_search_baidu()